#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
适配器模式 (Adapter Pattern) - Python实现详解

概述引导：
适配器模式允许不兼容的接口协同工作，就像电源适配器一样。
对于Java工程师来说，Python的适配器模式实现更加灵活和动态。

学习要点：
1. 对象适配器vs类适配器
2. Python的多重继承优势
3. 动态适配器实现
4. 装饰器适配器模式

Java对比要点：
- Java主要使用对象适配器（组合）
- Python支持多重继承，可实现类适配器
- Python的duck typing使适配更灵活
- Python支持动态属性和方法

关键理解：
适配器模式解决接口不兼容问题，Python的动态特性使实现更简洁。
"""

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Protocol
import json
import xml.etree.ElementTree as ET
from dataclasses import dataclass
from functools import wraps


# ============= 目标接口 =============

class MediaPlayer(ABC):
    """
    媒体播放器接口 - 目标接口
    
    Java对比：
    - Java使用interface关键字
    - Python使用ABC更灵活
    """
    
    @abstractmethod
    def play(self, audio_type: str, filename: str) -> str:
        """播放音频文件"""
        pass


class DataProcessor(Protocol):
    """
    数据处理器协议 - 使用Protocol定义接口
    
    Python特色：
    - Protocol支持结构化子类型
    - 更灵活的接口定义
    """
    
    def process(self, data: Any) -> Dict[str, Any]:
        """处理数据"""
        ...


# ============= 被适配的类 =============

class Mp3Player:
    """
    MP3播放器 - 被适配的类
    
    这是一个已存在的类，接口与目标不兼容
    """
    
    def play_mp3(self, filename: str) -> str:
        """播放MP3文件"""
        return f"正在播放MP3文件: {filename}"


class Mp4Player:
    """
    MP4播放器 - 另一个被适配的类
    """
    
    def play_mp4(self, filename: str) -> str:
        """播放MP4文件"""
        return f"正在播放MP4文件: {filename}"


class VlcPlayer:
    """
    VLC播放器 - 支持多种格式
    """
    
    def play_vlc(self, filename: str) -> str:
        """播放VLC支持的文件"""
        return f"正在使用VLC播放: {filename}"
    
    def play_avi(self, filename: str) -> str:
        """播放AVI文件"""
        return f"正在播放AVI文件: {filename}"


class LegacyXmlParser:
    """
    遗留XML解析器 - 旧接口
    """
    
    def parse_xml_string(self, xml_string: str) -> ET.Element:
        """解析XML字符串"""
        return ET.fromstring(xml_string)
    
    def xml_to_dict(self, element: ET.Element) -> Dict[str, Any]:
        """XML转字典"""
        result = {}
        if element.text and element.text.strip():
            result['text'] = element.text.strip()
        
        for child in element:
            child_data = self.xml_to_dict(child)
            if child.tag in result:
                if not isinstance(result[child.tag], list):
                    result[child.tag] = [result[child.tag]]
                result[child.tag].append(child_data)
            else:
                result[child.tag] = child_data
        
        result.update(element.attrib)
        return result


class LegacyJsonParser:
    """
    遗留JSON解析器 - 旧接口
    """
    
    def load_json_from_string(self, json_string: str) -> Dict[str, Any]:
        """从字符串加载JSON"""
        return json.loads(json_string)
    
    def format_json_output(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """格式化JSON输出"""
        return {
            'status': 'success',
            'data': data,
            'format': 'json'
        }


# ============= 对象适配器 =============

class MediaAdapter(MediaPlayer):
    """
    媒体适配器 - 对象适配器实现
    
    Java对比：
    - Java通常使用这种组合方式
    - Python实现更简洁
    - 支持动态添加适配器
    """
    
    def __init__(self):
        # 组合不同的播放器
        self.mp3_player = Mp3Player()
        self.mp4_player = Mp4Player()
        self.vlc_player = VlcPlayer()
    
    def play(self, audio_type: str, filename: str) -> str:
        """适配不同格式的播放"""
        audio_type = audio_type.lower()
        
        if audio_type == "mp3":
            return self.mp3_player.play_mp3(filename)
        elif audio_type == "mp4":
            return self.mp4_player.play_mp4(filename)
        elif audio_type in ["vlc", "avi"]:
            if audio_type == "avi":
                return self.vlc_player.play_avi(filename)
            else:
                return self.vlc_player.play_vlc(filename)
        else:
            return f"不支持的音频格式: {audio_type}"


class AudioPlayer(MediaPlayer):
    """
    音频播放器 - 使用适配器
    
    这是客户端使用的主要类
    """
    
    def __init__(self):
        self.adapter = MediaAdapter()
    
    def play(self, audio_type: str, filename: str) -> str:
        """播放音频文件"""
        audio_type = audio_type.lower()
        
        if audio_type == "mp3":
            # 直接支持MP3
            return f"内置播放器正在播放MP3: {filename}"
        else:
            # 使用适配器播放其他格式
            return self.adapter.play(audio_type, filename)


# ============= 类适配器 (Python特色) =============

class Mp3ClassAdapter(MediaPlayer, Mp3Player):
    """
    MP3类适配器 - 使用多重继承
    
    Python优势：
    - 支持多重继承
    - 可以直接继承被适配类的功能
    - Java无法实现真正的类适配器
    """
    
    def play(self, audio_type: str, filename: str) -> str:
        """适配play方法"""
        if audio_type.lower() == "mp3":
            return self.play_mp3(filename)
        else:
            return f"类适配器不支持格式: {audio_type}"


class VlcClassAdapter(MediaPlayer, VlcPlayer):
    """
    VLC类适配器 - 多重继承实现
    """
    
    def play(self, audio_type: str, filename: str) -> str:
        """适配VLC播放器"""
        audio_type = audio_type.lower()
        
        if audio_type == "vlc":
            return self.play_vlc(filename)
        elif audio_type == "avi":
            return self.play_avi(filename)
        else:
            return f"VLC适配器不支持格式: {audio_type}"


# ============= 数据处理适配器 =============

class XmlDataAdapter:
    """
    XML数据适配器 - 适配遗留XML解析器
    """
    
    def __init__(self):
        self.xml_parser = LegacyXmlParser()
    
    def process(self, data: str) -> Dict[str, Any]:
        """处理XML数据"""
        try:
            xml_element = self.xml_parser.parse_xml_string(data)
            parsed_data = self.xml_parser.xml_to_dict(xml_element)
            return {
                'status': 'success',
                'data': parsed_data,
                'format': 'xml',
                'root_tag': xml_element.tag
            }
        except Exception as e:
            return {
                'status': 'error',
                'error': str(e),
                'format': 'xml'
            }


class JsonDataAdapter:
    """
    JSON数据适配器 - 适配遗留JSON解析器
    """
    
    def __init__(self):
        self.json_parser = LegacyJsonParser()
    
    def process(self, data: str) -> Dict[str, Any]:
        """处理JSON数据"""
        try:
            parsed_data = self.json_parser.load_json_from_string(data)
            return self.json_parser.format_json_output(parsed_data)
        except Exception as e:
            return {
                'status': 'error',
                'error': str(e),
                'format': 'json'
            }


# ============= 动态适配器 (Python特色) =============

class DynamicAdapter:
    """
    动态适配器 - Python特色实现
    
    Python优势：
    - 支持动态添加方法
    - 运行时修改行为
    - 更灵活的适配策略
    """
    
    def __init__(self):
        self._adapters = {}
        self._instances = {}
    
    def register_adapter(self, format_type: str, adapter_class, *args, **kwargs):
        """注册适配器"""
        self._adapters[format_type] = adapter_class
        self._instances[format_type] = adapter_class(*args, **kwargs)
    
    def process(self, format_type: str, data: Any) -> Dict[str, Any]:
        """动态处理数据"""
        if format_type in self._instances:
            adapter = self._instances[format_type]
            if hasattr(adapter, 'process'):
                return adapter.process(data)
            else:
                return {'status': 'error', 'error': f'适配器 {format_type} 没有process方法'}
        else:
            return {'status': 'error', 'error': f'未找到适配器: {format_type}'}
    
    def list_adapters(self) -> List[str]:
        """列出所有注册的适配器"""
        return list(self._adapters.keys())


# ============= 装饰器适配器 (Python特色) =============

def adapter_decorator(target_method: str):
    """
    装饰器适配器 - Python特色实现
    
    将方法调用适配到目标方法
    """
    def decorator(func):
        @wraps(func)
        def wrapper(self, *args, **kwargs):
            # 获取目标方法
            if hasattr(self, target_method):
                target_func = getattr(self, target_method)
                return target_func(*args, **kwargs)
            else:
                return func(self, *args, **kwargs)
        return wrapper
    return decorator


class DecoratorAdapterExample:
    """
    装饰器适配器示例
    """
    
    def old_method(self, data: str) -> str:
        """旧方法实现"""
        return f"旧方法处理: {data}"
    
    @adapter_decorator('old_method')
    def new_method(self, data: str) -> str:
        """新方法 - 适配到旧方法"""
        return f"新方法处理: {data}"


# ============= 演示函数 =============

def demonstrate_adapter_pattern():
    """
    演示适配器模式的使用
    
    概述引导：
    展示适配器模式在Python中的多种实现方式，
    包括对象适配器、类适配器和动态适配器。
    
    学习要点：
    1. 对象适配器的组合方式
    2. 类适配器的继承方式
    3. 动态适配器的灵活性
    4. 装饰器适配器的简洁性
    
    关键理解：
    适配器模式解决接口不兼容问题，使现有类能够与其他类协同工作。
    """
    print("=== 适配器模式演示 ===")
    print("\n学习目标：")
    print("- 理解适配器模式的作用")
    print("- 掌握对象适配器和类适配器")
    print("- 学习动态适配器实现")
    print("\n重点概念：")
    print("- 接口不兼容问题的解决")
    print("- 组合vs继承的选择")
    print("- Python多重继承的优势")
    print("=" * 50)
    
    # 1. 对象适配器演示
    print("\n1. 对象适配器演示：")
    player = AudioPlayer()
    
    test_files = [
        ("mp3", "song.mp3"),
        ("mp4", "video.mp4"),
        ("vlc", "movie.vlc"),
        ("avi", "clip.avi"),
        ("wav", "audio.wav")  # 不支持的格式
    ]
    
    for audio_type, filename in test_files:
        result = player.play(audio_type, filename)
        print(f"{audio_type.upper()}: {result}")
    
    # 2. 类适配器演示
    print("\n2. 类适配器演示：")
    mp3_adapter = Mp3ClassAdapter()
    vlc_adapter = VlcClassAdapter()
    
    print("MP3类适配器:")
    print(mp3_adapter.play("mp3", "test.mp3"))
    print(mp3_adapter.play("wav", "test.wav"))
    
    print("\nVLC类适配器:")
    print(vlc_adapter.play("vlc", "test.vlc"))
    print(vlc_adapter.play("avi", "test.avi"))


def demonstrate_data_adapters():
    """
    演示数据处理适配器
    """
    print("\n=== 数据处理适配器演示 ===")
    
    # XML数据适配器
    xml_adapter = XmlDataAdapter()
    xml_data = """
    <person id="1">
        <name>张三</name>
        <age>30</age>
        <address>
            <city>北京</city>
            <country>中国</country>
        </address>
    </person>
    """
    
    print("XML数据处理：")
    xml_result = xml_adapter.process(xml_data)
    print(json.dumps(xml_result, ensure_ascii=False, indent=2))
    
    # JSON数据适配器
    json_adapter = JsonDataAdapter()
    json_data = '''
    {
        "name": "李四",
        "age": 25,
        "skills": ["Python", "Java"]
    }
    '''
    
    print("\nJSON数据处理：")
    json_result = json_adapter.process(json_data)
    print(json.dumps(json_result, ensure_ascii=False, indent=2))


def demonstrate_dynamic_adapter():
    """
    演示动态适配器
    """
    print("\n=== 动态适配器演示 ===")
    
    # 创建动态适配器
    dynamic_adapter = DynamicAdapter()
    
    # 注册适配器
    dynamic_adapter.register_adapter('xml', XmlDataAdapter)
    dynamic_adapter.register_adapter('json', JsonDataAdapter)
    
    print("已注册的适配器：")
    for adapter_type in dynamic_adapter.list_adapters():
        print(f"- {adapter_type}")
    
    # 测试数据
    test_data = {
        'xml': '<root><message>Hello XML</message></root>',
        'json': '{"message": "Hello JSON"}'
    }
    
    print("\n动态处理不同格式数据：")
    for format_type, data in test_data.items():
        result = dynamic_adapter.process(format_type, data)
        print(f"\n{format_type.upper()}处理结果：")
        print(json.dumps(result, ensure_ascii=False, indent=2))
    
    # 测试未注册的格式
    print("\n测试未注册格式：")
    result = dynamic_adapter.process('yaml', 'test: data')
    print(json.dumps(result, ensure_ascii=False, indent=2))


def demonstrate_decorator_adapter():
    """
    演示装饰器适配器
    """
    print("\n=== 装饰器适配器演示 ===")
    
    example = DecoratorAdapterExample()
    
    print("调用旧方法：")
    print(example.old_method("测试数据"))
    
    print("\n调用新方法（适配到旧方法）：")
    print(example.new_method("测试数据"))


def demonstrate_java_comparison():
    """
    Java对比演示
    
    Java等价代码：
    ```java
    // Java版本的适配器模式
    public interface MediaPlayer {
        void play(String audioType, String fileName);
    }
    
    public class Mp3Player {
        public void playMp3(String fileName) {
            System.out.println("Playing mp3 file: " + fileName);
        }
    }
    
    public class MediaAdapter implements MediaPlayer {
        private Mp3Player mp3Player;
        private Mp4Player mp4Player;
        
        public MediaAdapter() {
            mp3Player = new Mp3Player();
            mp4Player = new Mp4Player();
        }
        
        @Override
        public void play(String audioType, String fileName) {
            if (audioType.equalsIgnoreCase("mp3")) {
                mp3Player.playMp3(fileName);
            } else if (audioType.equalsIgnoreCase("mp4")) {
                mp4Player.playMp4(fileName);
            }
        }
    }
    
    // Java无法实现真正的类适配器（单继承限制）
    // 只能使用接口实现类似效果
    ```
    
    Python优势：
    1. 多重继承支持真正的类适配器
    2. duck typing使适配更灵活
    3. 动态特性支持运行时适配
    4. 装饰器提供更简洁的适配方式
    """
    print("\n=== Java对比说明 ===")
    print("\nPython优势：")
    print("1. 多重继承支持类适配器")
    print("2. duck typing使接口更灵活")
    print("3. 动态适配器支持运行时注册")
    print("4. 装饰器适配器更简洁")
    print("5. Protocol提供结构化子类型")
    
    print("\nJava特点：")
    print("1. 单继承限制，主要使用对象适配器")
    print("2. 接口实现更严格")
    print("3. 编译时类型检查")
    print("4. 需要显式接口声明")


def performance_comparison():
    """
    性能对比测试
    """
    import time
    
    print("\n=== 性能对比 ===")
    
    # 创建测试对象
    object_adapter = MediaAdapter()
    class_adapter = Mp3ClassAdapter()
    dynamic_adapter = DynamicAdapter()
    dynamic_adapter.register_adapter('xml', XmlDataAdapter)
    
    # 测试对象适配器
    start_time = time.time()
    for i in range(10000):
        result = object_adapter.play("mp3", "test.mp3")
    object_time = time.time() - start_time
    
    # 测试类适配器
    start_time = time.time()
    for i in range(10000):
        result = class_adapter.play("mp3", "test.mp3")
    class_time = time.time() - start_time
    
    # 测试动态适配器
    xml_data = "<test>data</test>"
    start_time = time.time()
    for i in range(1000):  # 较少次数，因为XML解析较慢
        result = dynamic_adapter.process("xml", xml_data)
    dynamic_time = time.time() - start_time
    
    print(f"对象适配器 (10000次): {object_time:.4f}秒")
    print(f"类适配器 (10000次): {class_time:.4f}秒")
    print(f"动态适配器 (1000次): {dynamic_time:.4f}秒")
    print(f"类适配器比对象适配器快: {object_time/class_time:.2f}倍")


if __name__ == "__main__":
    demonstrate_adapter_pattern()
    demonstrate_data_adapters()
    demonstrate_dynamic_adapter()
    demonstrate_decorator_adapter()
    demonstrate_java_comparison()
    performance_comparison()